package com.example.springboot.Transaction.Service;

import com.example.springboot.Transaction.Dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

// 声明式事务
@Transactional(readOnly = false)
@Component
@Service
public class StudentService_02 {

    @Autowired
    private StudentDao studentDao;

    @Transactional //加了事务注解就是开启了事务，如果执行过程中报错，那么报错前的更改也不会提交（回滚）
    public void changeInfo_01(){
        studentDao.updateAgeById(22,1);
        int i=1/0; //这里故意让他报错
        System.out.println("-----------");
        studentDao.updateNameById("test33",1);
    }

    @Transactional(readOnly = true) //事务开启了只读后，方法中如果有更改数据，就会报错回滚，只读属性一般是加在类上
    public void changeInfo_02(){
        studentDao.updateAgeById(22,1);
        System.out.println("-----------");
        studentDao.updateNameById("test33",1);
    }

    @Transactional(readOnly = false,timeout = 3) //事务加了超时属性，超时后就会报错回滚 (默认: -1 永不超时,不限制事务时间)
    public void changeInfo_03(){
        studentDao.updateAgeById(33,1);

        try {
            Thread.sleep(4000); //睡眠4s，故意让他超时
        }catch (InterruptedException e){
            throw new RuntimeException(e);
        }

        System.out.println("-----------");
        studentDao.updateNameById("test33",1);
    }

    //rollbackFor = 指定哪些异常才会回滚,默认是 RuntimeException and Error 异常方可回滚
    @Transactional(readOnly = false,timeout = 3,rollbackFor = ClassNotFoundException.class)
    public void changeInfo_04() throws ClassNotFoundException {

        studentDao.updateAgeById(40,1);

        //主动抛出一个检查异常,测试
        throw new ClassNotFoundException();

    }

    //noRollbackFor = 指定哪些异常不会回滚, 默认没有指定,如果指定,应该在rollbackFor的范围内
    @Transactional(readOnly = false,timeout = 3,noRollbackFor = NullPointerException.class)
    public void changeInfo_05()  {
        studentDao.updateAgeById(55, 1);

        //主动抛出一个检查异常,测试
        int i = 1/0;

        studentDao.updateNameById("test55", 1);
    }

    @Transactional(isolation = Isolation.REPEATABLE_READ) //isolation = 设置事务的隔离级别,mysql默认是repeatable_read
    public void changeInfo_06(){
        studentDao.updateAgeById(33,1);
        System.out.println("-----------");
        studentDao.updateNameById("test33",1);
    }


    @Transactional //propagation事务传播行为属性。
    public void changeInfo_07(){
        changeAge();
        changeName();
    }

    /**
     * 声明两个独立修改数据库的事务业务方法
     * REQUIRED 表示当前方法必须运行在事务中。如果当前事务存在，方法将会在该事务中运行。否则，会启动一个新的事务
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void changeAge(){
        studentDao.updateAgeById(11,1);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void changeName(){
        studentDao.updateNameById("test1",1);
        int i = 1/0;
    }


}